package com.wn.naturalbiorhythms.tool;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * 
 * */
public class NaturalBiorhythmsAlgorithm {

	public static final long ONE_DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
	public static final byte T_physical = 23;
	public static final byte T_emotional = 28;
	public static final byte T_intellictual = 33;
	public static final byte T_intuitive = 38;
	
	public static final byte Day_Cycle = 0;//周期日
	public static final byte Day_Critical_physical = 12;//体力临界日
	public static final byte Day_Critical_emotional = 14;//情绪临界日
	public static final byte Day_Critical_intellictual = 17;//智力临界日
	public static final byte Day_Critical_intuitive = 19;//直觉临界日
	
	public static SimpleDateFormat SDF_DATE_yyyy_MM_dd = new SimpleDateFormat("yyyy-MM-dd");
	private long birthdayMilliseconds;
	private long livedDaysMilliseconds;
	private long livedDays;
	private String birthdayStr;
	public NaturalBiorhythmsAlgorithm(long birthday){
		this.birthdayMilliseconds = birthday;
		try {
			Date today = SDF_DATE_yyyy_MM_dd.parse(SDF_DATE_yyyy_MM_dd.format(new Date()));//
			livedDaysMilliseconds = today.getTime() - birthdayMilliseconds;
			livedDays = livedDaysMilliseconds / ONE_DAY_MILLISECONDS;
			birthdayStr = SDF_DATE_yyyy_MM_dd.format(new Date(birthday));
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}
	
	public String getBirthday(){
		return birthdayStr;
	}
	
	/**从生日到指定某日共经历天数*/
	public long getLivedDays(long toTime){
		if(toTime<=birthdayMilliseconds){
			return 0;
		}
		return (toTime-birthdayMilliseconds)/ONE_DAY_MILLISECONDS;
	}
	
	/**从生日到今日共经历天数*/
	public long getLivedDays(){
		return livedDays;
	}
	
	public long getLivedDaysMilliseconds(){
		return livedDaysMilliseconds;
	}
	
	/**在周期里的某一天*/
	public byte getDayInCyclePhysical(long _livedDays){
		return (byte)(_livedDays % T_physical);
	}
	/**在周期里的某一天*/
	public byte getDayInCycleEmotional(long _livedDays){
		return (byte)(_livedDays % T_emotional);
	}
	/**在周期里的某一天*/
	public byte getDayInCycleIntellictual(long _livedDays){
		return (byte)(_livedDays % T_intellictual);
	}
	/**在周期里的某一天*/
	public byte getDayInCycleIntuitive(long _livedDays){
		return (byte)(_livedDays % T_intuitive);
	} 
	
	
	/**周期日*/
	private List<Long> getDaysIn_CycleDay(long fromeTime,long toTime, byte cycleT,byte criticalType){
		List<Long> dayList = new ArrayList<Long>();
		long start = fromeTime>=birthdayMilliseconds?fromeTime:birthdayMilliseconds;
		for(long i = start;i<=toTime;i = i+ONE_DAY_MILLISECONDS){
			long livedDays = getLivedDays(i);
			
			if(livedDays%cycleT == criticalType){
				dayList.add(Long.valueOf(i));
			}
		}
		
		return dayList;
	}
	
	/**体力周期日*/
	public List<Long> getDaysIn_CycleDay_Physical(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_physical,Day_Cycle);
	}
	/**情绪周期日*/
	public List<Long> getDaysIn_CycleDay_Emotional(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_emotional,Day_Cycle);
	}
	/**智力周期日*/
	public List<Long> getDaysIn_CycleDay_Intellictual(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_intellictual,Day_Cycle);
	}
	/**直觉周期日*/
	public List<Long> getDaysIn_CycleDay_Intuitive(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_intuitive,Day_Cycle);
	}
	
	/**体力临界日*/
	public List<Long> getDaysIn_CriticalDay_Physical(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_physical, Day_Critical_physical);
	}
	/**情绪临界日*/
	public List<Long> getDaysIn_CriticalDay_Emotional(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_emotional, Day_Critical_emotional);
	}
	/**智力临界日*/
	public List<Long> getDaysIn_CriticalDay_Intellictual(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_intellictual, Day_Critical_intellictual);
	}
	/**直觉临界日*/
	public List<Long> getDaysIn_CriticalDay_Intuitive(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_intuitive, Day_Critical_intuitive);
	}
	
	/**高潮期*/
	private List<Long> getDaysIn_Highttide_Days(long fromeTime,long toTime, byte cycleT,byte criticalType){
		List<Long> dayList = new ArrayList<Long>();
		long start = fromeTime>=birthdayMilliseconds?fromeTime:birthdayMilliseconds;
		for(long i = start;i<=toTime;i = i+ONE_DAY_MILLISECONDS){
			long livedDays = getLivedDays(i);
			
			if(livedDays%cycleT < criticalType){
				dayList.add(Long.valueOf(i));
			}
		}
		
		return dayList;
	}
	/**低潮期*/
	private List<Long> getDaysIn_Lowtide_Days(long fromeTime,long toTime, byte cycleT,byte criticalType){
		List<Long> dayList = new ArrayList<Long>();
		long start = fromeTime>=birthdayMilliseconds?fromeTime:birthdayMilliseconds;
		for(long i = start;i<=toTime;i = i+ONE_DAY_MILLISECONDS){
			long livedDays = getLivedDays(i);
			
			if(livedDays%cycleT > criticalType){
				dayList.add(Long.valueOf(i));
			}
		}
		
		return dayList;
	}
	
	/**体力低潮期*/
	public List<Long> getDaysIn_Lowtide_Physical(long fromeTime,long toTime){
		return getDaysIn_Lowtide_Days(fromeTime, toTime, T_physical, Day_Critical_physical);
	}
	/**情绪低潮期*/
	public List<Long> getDaysIn_Lowtide_Emotional(long fromeTime,long toTime){
		return getDaysIn_Lowtide_Days(fromeTime, toTime, T_emotional, Day_Critical_emotional);
	}/**智力低潮期*/
	public List<Long> getDaysIn_Lowtide_Intellictual(long fromeTime,long toTime){
		return getDaysIn_Lowtide_Days(fromeTime, toTime, T_intellictual, Day_Critical_intellictual);
	}/**直觉低潮期*/
	public List<Long> getDaysIn_Lowtide_Intuitive(long fromeTime,long toTime){
		return getDaysIn_Lowtide_Days(fromeTime, toTime, T_intuitive, Day_Critical_intuitive);
	}
	
	/**体力高潮期*/
	public List<Long> getDaysIn_Hightide_Physical(long fromeTime,long toTime){
		return getDaysIn_Highttide_Days(fromeTime, toTime, T_physical, Day_Critical_physical);
	}
	/**情绪高潮期*/
	public List<Long> getDaysIn_Hightide_Emotional(long fromeTime,long toTime){
		return getDaysIn_Highttide_Days(fromeTime, toTime, T_emotional, Day_Critical_emotional);
	}/**智力高潮期*/
	public List<Long> getDaysIn_Hightide_Intellictual(long fromeTime,long toTime){
		return getDaysIn_Highttide_Days(fromeTime, toTime, T_intellictual, Day_Critical_intellictual);
	}/**直觉高潮期*/
	public List<Long> getDaysIn_Hightide_Intuitive(long fromeTime,long toTime){
		return getDaysIn_Highttide_Days(fromeTime, toTime, T_intuitive, Day_Critical_intuitive);
	}
	
	/**体力最高期*/
	public List<Long> getDaysIn_Highest_Physical(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_physical, (byte)(Day_Critical_physical/2));
	}
	/**情绪最高期*/
	public List<Long> getDaysIn_Highest_Emotional(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_emotional, (byte)(Day_Critical_emotional/2));
	} 
	
	/**智力最高期*/
	public List<Long> getDaysIn_Highest_Intellictual(long fromeTime,long toTime){
		List<Long> data1 = getDaysIn_CycleDay(fromeTime, toTime, T_intellictual, (byte)(Day_Critical_intellictual/2));
		List<Long> data2 = getDaysIn_CycleDay(fromeTime, toTime, T_intellictual, (byte)(Day_Critical_intellictual/2+1));
		data1.addAll(data2);
		Collections.sort(data1);
		return data1;
	} 
	/**直觉最高期*/
	public List<Long> getDaysIn_Highest_Intuitive(long fromeTime,long toTime){
		List<Long> data1 = getDaysIn_CycleDay(fromeTime, toTime, T_intuitive, (byte)(Day_Critical_intuitive/2));
		List<Long> data2 = getDaysIn_CycleDay(fromeTime, toTime, T_intuitive, (byte)(Day_Critical_intuitive/2+1));
		data1.addAll(data2);
		Collections.sort(data1);
		return data1;
	} 
	
	/**体力最低期*/
	public List<Long> getDaysIn_Lowest_Physical(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_physical, (byte)(Day_Critical_physical*3/2));
	}
	/**情绪最低期*/
	public List<Long> getDaysIn_Lowest_Emotional(long fromeTime,long toTime){
		return getDaysIn_CycleDay(fromeTime, toTime, T_emotional, (byte)(Day_Critical_emotional*3/2));
	} 
	
	/**智力最低期*/
	public List<Long> getDaysIn_Lowest_Intellictual(long fromeTime,long toTime){
		List<Long> data1 = getDaysIn_CycleDay(fromeTime, toTime, T_intellictual, (byte)(Day_Critical_intellictual*3/2));
		List<Long> data2 = getDaysIn_CycleDay(fromeTime, toTime, T_intellictual, (byte)(Day_Critical_intellictual*3/2+1));
		data1.addAll(data2);
		Collections.sort(data1);
		return data1;
	} 
	/**直觉最低期*/
	public List<Long> getDaysIn_Lowest_Intuitive(long fromeTime,long toTime){
		List<Long> data1 = getDaysIn_CycleDay(fromeTime, toTime, T_intuitive, (byte)(Day_Critical_intuitive*3/2));
		List<Long> data2 = getDaysIn_CycleDay(fromeTime, toTime, T_intuitive, (byte)(Day_Critical_intuitive*3/2+1));
		data1.addAll(data2);
		Collections.sort(data1);
		return data1;
	} 
	
	public static float getValuePhysical(long startday,int offset){
		return (float) (100 * Math.sin((startday + offset) % T_physical * Math.PI / Day_Critical_physical));
	}
	public static float getValueEmotional(long startday,int offset){
		return (float) (100 * Math.sin((startday + offset) % T_emotional * Math.PI / Day_Critical_emotional));
	}
	public static float getValueIntellictual(long startday,int offset){
		return (float) (100 * Math.sin((startday + offset) % T_intellictual * Math.PI / Day_Critical_intellictual));
	}
	public static float getValueIntuitive(long startday,int offset){
		return (float) (100 * Math.sin((startday + offset) % T_intuitive * Math.PI / Day_Critical_intuitive));
	}
}
